#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
Created on 30 jun 2011

@author: Joakim Lindskog

Copyright (c) 2011 Joakim Lindskog

This file is part of MyGarden.

    MyGarden is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MyGarden is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MyGarden.  If not, see <http://www.gnu.org/licenses/>.
'''
import pyglet, config, re, os
from cocos.audio.effect import Effect, Sound

'''
Utility functions
'''

def load_image(name, default_image=-1, fix=True, loader=None):
    '''
    Utility function for loading images
    
    @param name: the name of the image
    @type: string
    
    @param default_image: a default image to use on failure
    @type default_image: Texture/TextureRegion/-1
    
    @return: a loaded image
    @rtype: Texture/TextureRegion
    '''
    try:
        if loader:
            img = loader.image(name)
        else:
            img = pyglet.resource.image(name)
    except pyglet.resource.ResourceNotFoundException:
        if default_image == -1 and not config.MISSING_IMAGE:
            default_image = load_image(config.MISSING_IMAGE_NAME)
        img = default_image
    if fix:
        return fix_border(img)
    else:
        return img

def fix_border(tex):
    '''
    Takes a pyglet Texture/TextureRegion and insets the texture
    coordinates by half a texel,
    allowing for sub-pixel blitting without interpolation
    with nearby regions within same texture atlas
    Learnt from bobmitch's reply here:
    http://markmail.org/message/5wlrhimn7yzevlf2#query:+page:1+mid:5wlrhimn7yzevlf2+state:results
    
    @param tex: the texture to fix
    @type tex: Texture/TextureRegion
    
    @return: a fixed Texture/TextureRegion
    @rtype: Texture/TextureRegion
    '''
    coord_width = tex.tex_coords[3] - tex.tex_coords[0]
    coord_height = tex.tex_coords[4] - tex.tex_coords[1]
    # Get tex coord half texel width
    x_adjust = (coord_width / tex.width) / 2.0
    # Get tex coord half texel width
    y_adjust = (coord_height / tex.height) / 2.0
    # Create new 12-tuple texture coordinate
    tex.tex_coords = (tex.tex_coords[0]+x_adjust,
                      tex.tex_coords[1]+y_adjust,
                      0,
                      tex.tex_coords[3]-x_adjust,
                      tex.tex_coords[4]+y_adjust,
                      0,
                      tex.tex_coords[6]-x_adjust,
                      tex.tex_coords[7]-y_adjust,
                      0,
                      tex.tex_coords[9]+x_adjust,
                      tex.tex_coords[10]-y_adjust,
                      0)
    return tex

def setup_animation(img, num_rows, num_columns, seconds_per_frame, frame_width=None, frame_height=None, row_padding=0, column_padding=0):
    '''
    Sets up an animation from a tiled image
    
    @param img: the name of the tiled image
    @type img: string
    
    @param num_rows: the number of image rows in the tiled image
    @type num_rows: int
    
    @param num_columns: the number of image columns in the tiled image
    @type num_columns: int
    
    @param seconds_per_frame: seconds per frame in the animation
    @type seconds_per_frame: int
    
    @param frame_width: the width of each frame
    @type frame_width: int
    
    @param frame_height: the height of each frame
    @type frame_height: int
    
    @param row_padding: number of pixels between each row
    @type row_padding: int
    
    @param column_padding: number of pixels between each column
    @type column_padding: int
    
    @return: an animation
    @rtype: Animation
    '''
    base_image = pyglet.resource.image(img)
    animation_grid = pyglet.image.ImageGrid(base_image, num_rows, num_columns, frame_width, frame_height, row_padding, column_padding)
    animation = animation_grid.get_animation(seconds_per_frame, True)
    return animation

def load_effect(name):
    '''
    Loads a sound effect by name
    
    @param name: the name of the sound effect
    @type name: string
    
    @return: the loaded effect
    @rtype: Effect
    '''
    return Effect(get_sound_path(name))

def load_sound(name):
    '''
    Loads a sound by name
    
    @param name: the name of the sound
    @type name: string
    
    @return: the loaded sound
    @rtype: Sound
    '''
    return Sound(get_sound_path(name))

def get_sound_path(name):
    '''
    Returns the absolute path of a sound file
    
    @param name: the name of the sound file
    @type name: string
    
    @return: the absolute path of the sound file
    @rtype: string
    '''
    dir = os.path.abspath(os.path.join(os.path.dirname(os.getcwd()),"data/sounds/",name))
    return str(dir)

def get_missing_image():
    '''
    @return: the default image for missing images
    @rtype: Texture/TextureRegion
    '''
    if not config.MISSING_IMAGE:
        config.MISSING_IMAGE = load_image(config.MISSING_IMAGE_NAME)
    return config.MISSING_IMAGE

def get_default_icon():
    '''
    @return: the default image for missing icons
    @rtype: Texture/TextureRegion
    '''
    if not config.DEFAULT_ICON:
        config.DEFAULT_ICON = load_image(config.DEFAULT_ICON_NAME)
    return config.DEFAULT_ICON

def get_text_width(font, text):
    '''
    Returns the width of the supplied text
    
    @param font: the font of the text
    @type font: Font
    
    @param text: the text
    @type text: string
    
    @return: the width of the text
    @rtype: int
    '''
    text = _remove_tags(text)
    glyphs = font.get_glyphs(text)
    advance = 0
    for ch in glyphs:
        advance += ch.advance
    return advance

def get_text_height(font, text, width):
    '''
    Returns the height of the supplied text
    
    @param font: the font of the text
    @type font: Font
    
    @param text: the text
    @type text: string
    
    @param width: the width of the text
    @type width: int
    
    @return: the height of the text
    @rtype: int
    '''
    text = _remove_tags(text)
    glyphs = font.get_glyphs(text)
    lines = 0
    gl_len = len(glyphs)
    while gl_len > 0:
        rm_gl = len(font.get_glyphs_for_width(text, width+1))
        gl_len -= rm_gl
        text = text[rm_gl:]
        lines += 1
    return (font.ascent+font.descent+font.size)*lines

def _remove_tags(text):
    '''
    Strip tags from the supplied text
    
    @param text: the text
    @type text: string
    
    @return: text stripped from tags
    @rtype: string
    '''
    p = re.compile('<br>')
    text = p.sub(' ', text)
    p = re.compile('\<((?!\>).)+\>')
    text = p.sub('', text)
    return text